﻿using System;
using System.Linq;

namespace cludg.Services.Content
{
	using Domain.Content.Stories;
	using Domain.Users;
	using Repository.Content;
	using Repository.Transactions;

	public class CommentService : ICommentService
	{
		protected readonly IContentRepository<Comment> CommentRepository;
		protected readonly IContentRepository<Story> StoryRepository;
		protected readonly ITransactionFactory TransactionFactory;

		public CommentService(
			IContentRepository<Comment> commentRepository,
			IContentRepository<Story> storyRepository,
			ITransactionFactory transactionFactory)
		{
			CommentRepository = commentRepository;
			StoryRepository = storyRepository;
			TransactionFactory = transactionFactory;
		}

		#region Implementation of ICommentService

		public Comment NewComment(string storyId, string parentCommentId, User author, string text)
		{
			// Check for story exists
			var commentStory = StoryRepository.Get().FirstOrDefault(story => story.Id == storyId);
			if (commentStory == null)
			{
				throw new ArgumentException(string.Format("Story with '{0}' storyId doesn't exists.", storyId),
					"storyId");
			}

			var addingComment = new Comment
				{
					Author = author,
					Text = text,
					// TODO: текущее время - это контекст. По идее надо вынести во внешную зависимость IClock.
					CreationTime = DateTime.Now,
				};

			using (var tran = TransactionFactory.BeginTransaction())
			{
				if (!String.IsNullOrEmpty(parentCommentId))
				{
					var parent = CommentRepository.ById(parentCommentId);
					if (parent == null)
						throw new ApplicationException(String.Format("Родительского комментария {0} не существует", parentCommentId));
					parent.AddChild(addingComment);
				}
	
				commentStory.AddComment(addingComment);
				StoryRepository.Save(commentStory);

				tran.Commit();
			}

			return addingComment;
		}

		public Comment ById(string commentId)
		{
			return CommentRepository.ById(commentId);
		}

		public void UpdateComment(Comment comment)
		{
			// Check for comment exists
			var commentFromRepo =  CommentRepository.ById(comment.Id);
			if (commentFromRepo == null)
			{
				throw new ArgumentException(string.Format("'{0}' doesn't exists.", comment),
					"comment");
			}

			// Update comment
			using (var tran = TransactionFactory.BeginTransaction())
			{
				var commentStory = commentFromRepo.Story;
				commentStory.UpdateComment(comment);
				StoryRepository.Save(commentStory);
				tran.Commit();
			}
		}

		#endregion
	}
}
